#include "EPSG/Entity.h"

/* EPSG Includes */
#include "EPSG/Shape.h"
#include "EPSG/Material.h"
#include "EPSG/Appearance.h"

/* System Includes */
#ifdef WIN32
	#include <Windows.h>
#endif

/* OpenGL Includes */
#include <GL/GL.h>

EPSG::Entity::Entity()
{
	_appearance = NULL;
	_shape = NULL;
	_polygonOffset =  false;
	_toonShading = false;
	_lineColor[0] = 0.0f;
	_lineColor[1] = 0.0f;
	_lineColor[2] = 0.0f;
	_lineColor[3] = 1.0f;
	_lineWidth = 2.0f;
}

EPSG::Entity::Entity( EPSG::Appearance* appearance, EPSG::Shape* shape )
{
	Entity();
	setAppearance( appearance );
	setShape( shape );
}

void EPSG::Entity::render()
{
	if( _shape == NULL )
		return;

	if( _appearance == NULL )
		_appearance = new EPSG::Material();

	if( _toonShading == true )
		toonRender();

	if( _polygonOffset == true )
	{
		glPushAttrib( GL_POLYGON_BIT );
		glEnable( GL_POLYGON_OFFSET_FILL );

		glPolygonMode( GL_FRONT, GL_FILL );
		glPolygonOffset( _factor, _units );
		printf( "polygon offset" );
	}

	bool hasTexCoords = _appearance->load();
	_shape->draw( !hasTexCoords );
	_appearance->unload();

	if( _polygonOffset == true )
	{
		glPopAttrib();
		glDisable( GL_POLYGON_OFFSET_FILL );
	}
}

void EPSG::Entity::toonRender()
{
	// Desenhando a silhueta
	glPushAttrib( GL_LIGHTING_BIT );
	glPushAttrib( GL_CURRENT_BIT );
	glPushAttrib( GL_LINE_BIT );
	glPushAttrib( GL_POLYGON_BIT ); 

	glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, _lineColor );

	glDisable( GL_LIGHTING );
	glEnable( GL_CULL_FACE );
	glCullFace( GL_FRONT );

	glEnable( GL_POLYGON_MODE );
	glEnable( GL_LINE_SMOOTH );

	glPolygonMode( GL_BACK, GL_LINE );
	glLineWidth( _lineWidth );
	glColor4fv( _lineColor );

	glEnable( GL_POLYGON_OFFSET_LINE );
	glPolygonOffset( 2.0f, 2.0f );

	_shape->draw( false );

	glEnable( GL_LIGHTING );
	glDisable( GL_CULL_FACE );
	glPopAttrib();
	glPopAttrib();
	glPopAttrib();
	glPopAttrib();
}

void EPSG::Entity::setAppearance( EPSG::Appearance* a )
{
	_appearance = a;
}

void EPSG::Entity::setShape( EPSG::Shape* s )
{
	_shape = s;
}

EPSG::Appearance* EPSG::Entity::getAppearance()
{
	return _appearance;
}

EPSG::Shape* EPSG::Entity::getShape()
{
	return _shape;
}

void EPSG::Entity::setPolygonOffset( float factor, float units )
{
	_factor = factor;
	_units = units;
	_polygonOffset = true;
}

void EPSG::Entity::setToonShading( bool toonShading )
{
	_toonShading = toonShading;
}

void EPSG::Entity::setToonBorderWidth( float width )
{
	_lineWidth = width;
}

void EPSG::Entity::setToonBorderColor( float r, float g, float b, float a )
{
	_lineColor[0] = r;
	_lineColor[1] = g;
	_lineColor[2] = b;
	_lineColor[3] = a;
}